package com.kun.portal.webframe.service;

import com.kun.portal.webframe.dao.DutyDao;
import com.kun.portal.webframe.po.DutyPo;
import com.kun.portal.webframe.po.FwTeamPo;
import com.kun.portal.webframe.po.FwUserPo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TemporalType;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;

/**
 * Created by Administrator on 2018/6/25.
 */
@Service
public class DutyService {
    @Autowired
    private DutyDao dutyDao;
    @Autowired
    private EntityManager entityManager;
    public List<DutyPo> query(Date startDate,Date endDate){
        List<Date> dates= entityManager.createQuery("select max(d.dutyDate) from  DutyPo  d").getResultList();
        if(null==dates||dates.size()==0||dates.get(0)==null||dates.get(0).getTime()<endDate.getTime()){
            Calendar calendar =  Calendar.getInstance();

            if(dates.get(0)!=null){
                Date date =dates.get(0);
                calendar.setTime(date);
                calendar.add(Calendar.DAY_OF_YEAR,1);
            }else {
                calendar.setTime(startDate);
            }

            this.createDuty(calendar.getTime(),endDate);
        }
//        Specification<DutyPo> query =  new Specification<DutyPo>() {
//            @Override
//            public Predicate toPredicate(Root<DutyPo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
//                Predicate predicate= cb.between(root.get("dutyDate"),startDate,endDate);
//                return predicate;
//            }
//        };
//        Sort sort =  new Sort(new Sort.Order(Sort.Direction.DESC,"dutyDate"));
//        List<DutyPo> list = dutyDao.findAll(query,sort);
       Query query =  entityManager.createQuery("select t ,u ,d from FwTeamPo t  left join  DutyPo  d on ( d.dutyDate >=  :startDate and d.dutyDate <=  :endDate and t.teamId = d.teamId) " +
                "left join FwUserPo u on u.userId = d.userId"   +
                "");

        query.setParameter("startDate",startDate, TemporalType.DATE);
        query.setParameter("endDate",endDate, TemporalType.DATE);

        return  query.getResultList();
    }
    private class CurrentDutyUser{
        private List<DutyPo> preUsers =  new ArrayList<>();
        private List<FwUserPo> allUsers ;
        private int index=-2;
        private boolean fondIndex = false;
        private FwUserPo  nextUser(){
            if(!fondIndex){
                preUsers.sort(new Comparator<DutyPo>() {
                    @Override
                    public int compare(DutyPo o1, DutyPo o2)
                    {
                        if(o1.getDutyDate().getTime()==o2.getDutyDate().getTime()){
                            return  o1.getIndex()>o1.getIndex()?1:-1;
                        }else{
                            return o1.getDutyDate().getTime()>o2.getDutyDate().getTime()?1:-1;
                        }

                    }
                });
                if(preUsers.size()>0){
                    String userId =preUsers.get(preUsers.size()-1).getUserId();
                    for(int i=0;i<allUsers.size();i++){
                        if(userId.equals(allUsers.get(i).getUserId())){
                            index=i;
                            fondIndex=true;
                        }
                    }
                }
            }
            if(!fondIndex){
                index=-1;
                fondIndex=true;
            }
            index = index+1;
            index = index%allUsers.size();
            return allUsers.get(index);
        }

    }
    @Transactional
    private List<DutyPo> createDuty(Date startDate,Date endDate){
        Calendar calendar = Calendar.getInstance();
        List<DutyPo> list =  new ArrayList<DutyPo>();
        List<FwTeamPo> teams = entityManager.createQuery("select t from FwTeamPo t  left join fetch t.dutyUser where not(t.teamStatus ='0' )  ").getResultList();
        List<DutyPo>   dutys = entityManager.createQuery("select d from DutyPo d  where d.dutyDate= (select max(t.dutyDate) from DutyPo t ) ").getResultList();
        Map<String,CurrentDutyUser> currentDuty =  new HashMap<String,CurrentDutyUser>();
        for(DutyPo dutyPo :dutys){
            if(currentDuty.get(dutyPo.getTeamId())==null){
                currentDuty.put(dutyPo.getTeamId(),new CurrentDutyUser());
            }
            CurrentDutyUser currentDutyUser =  currentDuty.get(dutyPo.getTeamId());
            currentDutyUser.preUsers.add(dutyPo);
        }
        for(FwTeamPo teamPo :teams){
            if(teamPo.getDutyUser()!=null&&teamPo.getDutyUser().size()>0){
                List<FwUserPo> lis =  new ArrayList(teamPo.getDutyUser());
                lis.sort(new Comparator<FwUserPo>() {
                    @Override
                    public int compare(FwUserPo o1, FwUserPo o2) {
                        return (o1.getUserId().hashCode()>o2.getUserId().hashCode()?1:-1);
                    }
                });
                if(currentDuty.get(teamPo.getTeamId())==null){
                    currentDuty.put(teamPo.getTeamId(),new CurrentDutyUser());
                }
                CurrentDutyUser currentDutyUser =  currentDuty.get(teamPo.getTeamId());
                currentDutyUser.allUsers = lis;
            }

        }
        for(calendar.setTime(startDate);
             startDate.getTime()<=endDate.getTime();
             calendar.add(Calendar.DAY_OF_YEAR,1),startDate = calendar.getTime()){

            for(FwTeamPo teamPo :teams){
                if(teamPo.getDutyUser()!=null&&teamPo.getDutyUser().size()>0){
                    for(int i=0;i<teamPo.getDutyBaseNum();i++){
                        DutyPo dutyPo =  new DutyPo();
                        dutyPo.setTeamId(teamPo.getTeamId());
                        CurrentDutyUser currentDutyUser=currentDuty.get(teamPo.getTeamId());
                        dutyPo.setUserId(currentDutyUser.nextUser().getUserId());
                        dutyPo.setIndex(currentDutyUser.index);
                        dutyPo.setDutyDate(startDate);
                        list.add(dutyPo);
                    }
                }
            }
        }
        list=dutyDao.save(list);
        return list;
    }
}
